/*
 * DSP Example is part of the DSP Lecture at TEC-Costa Rica
 * Copyright (C) 2010  Pablo Alvarado
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/**
 * \file   mainwindow.cpp
 *         Implements the equalizer H(w) computation
 * \author Pablo Alvarado
 * \date   2010.12.12
 *
 * $Id: equalizer.cpp $
 */

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "jack.h"
#include "common_defs.h"
#include "mainwindow.h"
#include <cmath>
#include <QApplication>
#include <cmath>
#include <string>

#include <qregexp.h>
#include <qtoolbar.h>
#include <qtoolbutton.h>
#include <qlabel.h>
#include <qlayout.h>
#include <qstatusbar.h>
#include <qprinter.h>
#include <qpicture.h>
#include <qpainter.h>
#include <qfiledialog.h>
#include <qimagewriter.h>
#include <qprintdialog.h>
#include <qfileinfo.h>
#include <qwt_counter.h>
#include <qwt_picker_machine.h>
#include <qwt_plot_zoomer.h>
#include <qwt_plot_panner.h>
#include <qwt_plot_renderer.h>
#include <qwt_text.h>
#include <qwt_math.h>

#include "mainwindow.h"

class Zoomer: public QwtPlotZoomer
{
public:
    Zoomer(int xAxis, int yAxis, QwtPlotCanvas *canvas):
        QwtPlotZoomer(xAxis, yAxis, canvas)
    {
        setTrackerMode(QwtPicker::AlwaysOff);
        setRubberBand(QwtPicker::NoRubberBand);

        // RightButton: zoom out by 1
        // Ctrl+RightButton: zoom out to full size

        setMousePattern(QwtEventPattern::MouseSelect2,
            Qt::RightButton, Qt::ControlModifier);
        setMousePattern(QwtEventPattern::MouseSelect3,
            Qt::RightButton);
    }
};

#undef _DSP_DEBUG
#define _DSP_DEBUG

#ifdef _DSP_DEBUG
#define _debug(x) std::cerr << x
#include <iostream>
#include <stdio.h>
#else
#define _debug(x)
#endif

/**
 * Precision used by trimming
 */
const float MainWindow::Epsilon = 0.001;


MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow),
    verbose_(false),
    eqChanged_(true)
{
    ui->setupUi(this);

    /* Managing the Volume slider */
    ui->volumeSlider->setValue(50);
    ui->volumeSlider->setRange(1,63);
    ui->volumeSlider->setSingleStep(5);
    ui->volumeSlider->setPageStep(15);
    ui->volumeSlider->setTickInterval(10);
    ui->volumeSlider->setTickPosition(QSlider::TicksBothSides);
    QTextStream(&vPos) << (int) ui->volumeSlider->value();

    /* The volume uses directly the alsa mixer daemon through a system cmd*/
    QString cmdInitPCM = "amixer -q sset 'Master' "+ vPos;
    system(cmdInitPCM.toLatin1().data());

    /* manage media buttons , They should be disabled */
    ui->playBut->setEnabled(false);
    ui->stopBut->setEnabled(false);

    /* initialization of spinboxes for cut frequencies on known values */
    ui->spFreqC1->setValue(INIT_FREC_C0);
    ui->spFreqC2->setValue(INIT_FREC_C1);

    /* Manage the freq2 label and spinbox  this object should be hideden on
     * system initialization, the cut frenquency 2 won't be enabled until user
     * selects the high pass filter */
    ui->lFreqC2->hide ();
    ui->spFreqC2->hide ();

    /* manage the IIR option */
    ui->spCutFreq1_IIR->show ();
    ui->spCutFreq2_IIR->hide ();
    ui->lCutFreq1_IIR->show ();
    ui->lCutFreq2_IIR->hide ();

    /* set initial label strings*/
    ui->lWindowType_FIR->setText ("RECT");
    ui->lfilterType_FIR->setText ("LOW PASS");

    /*
     * Set up a timer 4 times in a second to check if the user
     * changed the equalizer values, and if so, then create a new
     * filter response
     */
    timer_ = new QTimer(this);
    connect(timer_, SIGNAL(timeout()), this, SLOT(update()));

    timer_->start(250);

    dsp_ = new dspSystem;
    jack::init(dsp_);

    updateEqualizer();

    /* parse some command line arguments */
    QStringList argv(QCoreApplication::arguments());
    QStringList::const_iterator it(argv.begin());
    while(it!=argv.end())
    {
        if ((*it)=="-v" || (*it)=="--verbose")
        {
            verbose_=true;
        }
        else if ((*it).indexOf(".wav",0,Qt::CaseInsensitive)>0)
        {
            ui->fileEdit->setText(*it);
            std::string tmp(qPrintable(*it));
            jack::playAlso(tmp.c_str());
        }
        ++it;
    }

    /* Creation of new object for bodeplotting */
    d_plot = new Plot(ui->mymainwiddget);
    d_plot->resize (500,500);
    setContextMenuPolicy(Qt::NoContextMenu);

    d_zoomer[0] = new Zoomer( QwtPlot::xBottom, QwtPlot::yLeft,
                              d_plot->canvas());
    d_zoomer[0]->setRubberBand(QwtPicker::RectRubberBand);
    d_zoomer[0]->setRubberBandPen(QColor(Qt::green));
    d_zoomer[0]->setTrackerMode(QwtPicker::ActiveOnly);
    d_zoomer[0]->setTrackerPen(QColor(Qt::white));

    d_zoomer[1] = new Zoomer(QwtPlot::xTop, QwtPlot::yRight,
                             d_plot->canvas());

    d_panner = new QwtPlotPanner(d_plot->canvas());
    d_panner->setMouseButton(Qt::MidButton);

    d_picker = new QwtPlotPicker(QwtPlot::xBottom, QwtPlot::yLeft,
                                 QwtPlotPicker::CrossRubberBand, QwtPicker::AlwaysOn,
                                 d_plot->canvas());
    d_picker->setStateMachine(new QwtPickerDragPointMachine());
    d_picker->setRubberBandPen(QColor(Qt::green));
    d_picker->setRubberBand(QwtPicker::CrossRubberBand);
}

MainWindow::~MainWindow()
{
    jack::close();
    delete timer_;
    delete ui;
    delete dsp_;
}

void MainWindow::enableZoomMode(bool on)
{
    d_panner->setEnabled(on);

    d_zoomer[0]->setEnabled(on);
    d_zoomer[0]->zoom(0);

    d_zoomer[1]->setEnabled(on);
    d_zoomer[1]->zoom(0);

    d_picker->setEnabled(!on);

    showInfo();
}

void MainWindow::showInfo(QString text)
{
    if ( text == QString::null )
    {
        if ( d_picker->rubberBand() )
            text = "Cursor Pos: Press left mouse button in plot region";
        else
            text = "Zoom: Press mouse button and drag";
    }

#ifndef QT_NO_STATUSBAR
    statusBar()->showMessage(text);
#endif
}

void MainWindow::moved(const QPoint &pos)
{
    QString info;
    info.sprintf("Freq=%g, Ampl=%g, Phase=%g",
        d_plot->invTransform(QwtPlot::xBottom, pos.x()),
        d_plot->invTransform(QwtPlot::yLeft, pos.y()),
        d_plot->invTransform(QwtPlot::yRight, pos.y())
    );
    showInfo(info);
}

void MainWindow::selected(const QPolygon &)
{
    showInfo();
}

void MainWindow::update()
{
    if (eqChanged_)
    {
        _debug("Updating equalizer" << std::endl);
        dsp_->updateEqualizer();
        eqChanged_=false;
    }
}

/**
 * Convert a band value to the slider range
 */
int MainWindow::bandToSlider(const float band) const
{
    return static_cast<int>(band*50.0f + 0.5f);
}

/**
 * Convert a slider value to the band range
 */
float MainWindow::sliderToBand(const int val) const
{
    return float(val)/50.0;
}

/*
 * Reads the values on the real equalizer class an set the slider
 * values accordingly.
 */
void MainWindow::updateEqualizer()
{
    if (dsp_!=0)
    {
        equalizer& eq=*(dsp_->getEqualizer());
        int idx=0;
        ui->freq01Slider->setValue(bandToSlider(eq.getBand(idx++)));
        ui->freq02Slider->setValue(bandToSlider(eq.getBand(idx++)));
        ui->freq03Slider->setValue(bandToSlider(eq.getBand(idx++)));
        ui->freq04Slider->setValue(bandToSlider(eq.getBand(idx++)));
        ui->freq05Slider->setValue(bandToSlider(eq.getBand(idx++)));
        ui->freq06Slider->setValue(bandToSlider(eq.getBand(idx++)));
        ui->freq07Slider->setValue(bandToSlider(eq.getBand(idx++)));
        ui->freq08Slider->setValue(bandToSlider(eq.getBand(idx++)));
        ui->freq09Slider->setValue(bandToSlider(eq.getBand(idx++)));
        ui->freq10Slider->setValue(bandToSlider(eq.getBand(idx++)));
        ui->freq11Slider->setValue(bandToSlider(eq.getBand(idx++)));
        ui->freq12Slider->setValue(bandToSlider(eq.getBand(idx++)));
        ui->freq13Slider->setValue(bandToSlider(eq.getBand(idx++)));
        ui->freq14Slider->setValue(bandToSlider(eq.getBand(idx++)));
        ui->freq15Slider->setValue(bandToSlider(eq.getBand(idx++)));
        ui->freq16Slider->setValue(bandToSlider(eq.getBand(idx++)));
    }
}

void MainWindow::updateReverb()
{
    if (dsp_!=0)
    {
        reverb& rv = *(dsp_->getReverberator());

        ui->alphaSpinBox->setValue(rv.getAlpha());
        ui->delaySlider->setValue(static_cast<int>(rv.getDelay()+0.5f));
    }
}

void MainWindow::setFrequencySlider(
    const int idx,
    const int value)
{
    if (!eqChanged_)
    {
        eqChanged_=true;
        ui->presetsBox->setCurrentIndex(0);
    }
    float band = sliderToBand(value);
    dsp_->getEqualizer()->setBand(idx,band);
}

void MainWindow::on_freq01Slider_valueChanged(int value)
{
    setFrequencySlider(0,value);
}

void MainWindow::on_freq02Slider_valueChanged(int value)
{
    setFrequencySlider(1,value);
}

void MainWindow::on_freq03Slider_valueChanged(int value)
{
    setFrequencySlider(2,value);
}

void MainWindow::on_freq04Slider_valueChanged(int value)
{
    setFrequencySlider(3,value);
}

void MainWindow::on_freq05Slider_valueChanged(int value)
{
    setFrequencySlider(4,value);
}

void MainWindow::on_freq06Slider_valueChanged(int value)
{
    setFrequencySlider(5,value);
}

void MainWindow::on_freq07Slider_valueChanged(int value)
{
    setFrequencySlider(6,value);
}

void MainWindow::on_freq08Slider_valueChanged(int value)
{
    setFrequencySlider(7,value);
}

void MainWindow::on_freq09Slider_valueChanged(int value)
{
    setFrequencySlider(8,value);
}

void MainWindow::on_freq10Slider_valueChanged(int value)
{
    setFrequencySlider(9,value);
}

void MainWindow::on_freq11Slider_valueChanged(int value)
{
    setFrequencySlider(10,value);
}

void MainWindow::on_freq12Slider_valueChanged(int value)
{
    setFrequencySlider(11,value);
}

void MainWindow::on_freq13Slider_valueChanged(int value)
{
    setFrequencySlider(12,value);
}

void MainWindow::on_freq14Slider_valueChanged(int value)
{
    setFrequencySlider(13,value);
}

void MainWindow::on_freq15Slider_valueChanged(int value)
{
    setFrequencySlider(14,value);
}

void MainWindow::on_freq16Slider_valueChanged(int value)
{
    setFrequencySlider(15,value);
}

void MainWindow::on_alphaSpinBox_valueChanged(double value)
{
    ui->dialAlpha->setValue(static_cast<int>(value*1000.0+0.5));
    dsp_->getReverberator()->setAlpha(static_cast<float>(value));
}

void MainWindow::on_dialAlpha_dialMoved(int value)
{
    ui->alphaSpinBox->setValue(double(value)/1000.0);
}

void MainWindow::on_fileButton_clicked()
{
    selectedFiles_ =
            QFileDialog::getOpenFileNames(
                this,
                "Select one or more audio files to open",
                ui->fileEdit->text(),
                "WAV Files (*.wav)");

    if (!selectedFiles_.empty())
    {
        ui->fileEdit->setText(*selectedFiles_.begin());
        ui->stopBut->setEnabled(true);
        jack::stopFiles();
        QStringList::iterator it;
        for (it=selectedFiles_.begin(); it!=selectedFiles_.end(); ++it)
        {
            std::string tmp(qPrintable(*it));
            jack::playAlso(tmp.c_str());
        }
    }
}

void MainWindow::on_fileEdit_returnPressed()
{
    jack::stopFiles();
    std::string tmp(qPrintable(ui->fileEdit->text()));
    if (!tmp.empty())
    {
        jack::playAlso(tmp.c_str());
    }
}

void MainWindow::on_reverb_toggled(bool checked)
{
    _debug("Reverberator " << (checked?"activated":"deactivated") << std::endl);
    dsp_->setReverb(checked);
}

void MainWindow::on_equalizer_toggled(bool checked)
{
    _debug("Equalizer " << (checked?"activated":"deactivated") << std::endl);
    dsp_->setEqualizer(checked);
}

void MainWindow::on_filter60_toggled(bool checked)
{
    _debug("60 Hz filter " << (checked?"activated":"deactivated") << std::endl);
    dsp_->setFilter60(checked);
}

void MainWindow::on_iirfilter_toggled(bool checked)
{
    _debug("iirfilter " << (checked?"activated":"deactivated") << std::endl);
    dsp_->setIirfilter (checked);
}

void MainWindow::on_firfilter_toggled(bool checked)
{
    _debug("firfilter " << (checked?"activated":"deactivated") << std::endl);
    dsp_->setFirfilter (checked);
}

void MainWindow::on_presetsBox_currentIndexChanged(int index)
{
    _debug("MainWindow::on_presetsBox_currentIndexChanged(" << index << ")\n");

    static const float presets[5][16] =
    {
        {
            0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
            0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f
        },
        {
            1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
            1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f
        },
        {
            1.0f, 1.0f, 1.0f, 0.7f, 0.5f, 0.3f, 0.1f, 0.0f,
            0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f
        },
        {
            0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
            0.0f, 0.1f, 0.3f, 0.5f, 0.7f, 1.0f, 1.0f, 1.0f
        },
        {
            0.0f, 0.0f, 0.1f, 0.3f, 0.5f, 0.7f, 1.0f, 1.0f,
            1.0f, 1.0f, 0.7f, 0.5f, 0.3f, 0.1f, 0.0f, 0.0f
        }
    };

    if ((index>0) || !eqChanged_)
    {
        for (int n=0; n<16; ++n)
        {
            dsp_->getEqualizer()->setBand(n,presets[index][n]);
        }
        eqChanged_=true;
        updateEqualizer();
    }

}

void MainWindow::on_resetButton_clicked()
{
    dsp_->getReverberator()->reset();
}

void MainWindow::on_delaySlider_valueChanged(int value)
{
    dsp_->getReverberator()->setDelay(float(value));
}

void MainWindow::on_exitBut_clicked()
{
    this->close();
}

void MainWindow::on_playBut_clicked()
{
    /* extra functionality added, an play button has been added to help user
     * to manage the audio as on a media player
     */
    std::string tmp(qPrintable(ui->fileEdit->text()));
    if (ui->fileEdit->text() !="" )
    {
        if (!tmp.empty())
        {
            jack::playAlso(tmp.c_str());
        }
    }
    ui->playBut->setEnabled(false);
    ui->stopBut->setEnabled(true);

}

void MainWindow::on_stopBut_clicked()
{
    /* extra functionality added, an stop button has been added to help user
     * to manage the audio as on a media player
     */
    jack::stopFiles();
    ui->playBut->setEnabled(true);
    ui->stopBut->setEnabled(false);
}

void MainWindow::on_volumeSlider_valueChanged(int value)
{
    int ret;
    QString volumePos;
    QTextStream( &volumePos) << value;
    QString cmd2 = "amixer sset -q 'Master' " + volumePos;
    ret = system( cmd2.toLatin1().data());
    if (ret == 0)
    {
        ui->volumeLCD->display((int)value*(100.0/63.0));
    }
}

void MainWindow::on_resetIIRvalues_pressed()
{
   dsp_->getIirfilter ()->reset (&dsp_->getIirfilter ()->tIirMainStruct_);
   ui->spCutFreq1_IIR->setValue (INIT_FREC_C0);
   ui->spFIlterOrder_IIR->setValue (INIT_IIR_ORDER);
}

void MainWindow::on_resetFIRvalues_pressed()
{
    dsp_->getFirfilter ()->reset (&dsp_->getFirfilter ()->tFirMainStruct_);
    ui->lFreqC2->hide  ();
    ui->spFreqC2->hide ();
    ui->spFilterType->setValue (1);
    ui->spFilterWindowType->setValue (1);
    ui->spNumCoefs->setValue (MAX_FIR_ORDER);
    ui->spFreqC1->setValue (1000);
    ui->spFreqC2->setValue (1000);
}

void MainWindow::on_showfreq_clicked()
{

}

void MainWindow::on_spNumCoefs_valueChanged(int arg1)
{
    dsp_->getFirfilter ()->tFirMainStruct_.fir_order = arg1;
    dsp_->getFirfilter ()->tFirMainStruct_.hist_pos  = 0;

    /* When there is a change on order of filter the window must be calculated
     * again and if the window had been recalculated then the coeff must be
     * recalculated as well
     */
    dsp_->getFirfilter ()->GetWindow (
                dsp_->getFirfilter ()->tFirMainStruct_.window,
                dsp_->getFirfilter ()->tFirMainStruct_.firWinType,
                arg1+1);

    dsp_->getFirfilter ()->FirCoeff (
                dsp_->getFirfilter ()->tFirMainStruct_.coefs,
                arg1,
                dsp_->getFirfilter ()->tFirMainStruct_.fir_fc,
                dsp_->getFirfilter ()->tFirMainStruct_.firType,
                dsp_->getFirfilter ()->tFirMainStruct_.window);
}

void MainWindow::on_spFreqC1_valueChanged(int arg1)
{
    float fc0;
    float fc1;

    float fc_norm = static_cast<float>(arg1);

    /* Normalization of frequency */
    fc0 = (fc_norm/SAMPLING_FREQ)*2*M_PI;
    fc1 = dsp_->getFirfilter()->tFirMainStruct_.fir_fc[1];

    /* fc0 and fc1 should respect always the difference.
     * fc1 should always at least as the same value of fc0 , never lower
     */
    if (fc0 + FREC_ANG_MIN > fc1)
    {
        ui->spFreqC2->setValue(
                    static_cast<int>((fc0)*SAMPLING_FREQ/(2*M_PI))+FIR_MIN_BAND);
        dsp_->getFirfilter ()->tFirMainStruct_.fir_fc[1] = fc0 + FREC_ANG_MIN;
        dsp_->getFirfilter ()->tFirMainStruct_.fir_fc[0] = fc0;
    }
    else
    {
        dsp_->getFirfilter ()->tFirMainStruct_.fir_fc[0] = fc0;
    }


    /* On fc1 change the coef are re-calculated. Re-calculation of
     * window is not needed.
     */
    dsp_->getFirfilter ()->FirCoeff (
                dsp_->getFirfilter ()->tFirMainStruct_.coefs,
                dsp_->getFirfilter ()->tFirMainStruct_.fir_order,
                dsp_->getFirfilter ()->tFirMainStruct_.fir_fc,
                dsp_->getFirfilter ()->tFirMainStruct_.firType,
                dsp_->getFirfilter ()->tFirMainStruct_.window);
}

void MainWindow::on_spFreqC2_valueChanged(int arg2)
{
    float fc0;
    float fc1;
    fc0 = dsp_->getFirfilter()->tFirMainStruct_.fir_fc[0];
    float fc_norm = static_cast<float>(arg2);
    fc1 = (fc_norm/SAMPLING_FREQ)*2*M_PI;

    /* On fc1 change take count the value of fc0 should always be lower than fc1
     * this functions prevents this problem
     */
    if (fc1 - FREC_ANG_MIN < fc0)
    {
        ui->spFreqC1->setValue(
                    static_cast<int>((fc1)*SAMPLING_FREQ/(2*M_PI))-FIR_MIN_BAND);
        dsp_->getFirfilter ()->tFirMainStruct_.fir_fc[1] = fc1;
        dsp_->getFirfilter ()->tFirMainStruct_.fir_fc[0] = fc1 - FREC_ANG_MIN;

    }
    else
    {
        dsp_->getFirfilter ()->tFirMainStruct_.fir_fc[1] = fc1;
    }

    /* On fc change the coef are re-calculated. Re-calculation of
     * window is not needed.
     */
    dsp_->getFirfilter ()->FirCoeff (
                dsp_->getFirfilter ()->tFirMainStruct_.coefs,
                dsp_->getFirfilter ()->tFirMainStruct_.fir_order,
                dsp_->getFirfilter ()->tFirMainStruct_.fir_fc,
                dsp_->getFirfilter ()->tFirMainStruct_.firType,
                dsp_->getFirfilter ()->tFirMainStruct_.window);

}

void MainWindow::on_dspAtenuation_valueChanged(double dArg1)
{
    /* FIX: atenuation functions are not implemented */
    dsp_->getFirfilter ()->tFirMainStruct_.fir_atenuation = dArg1;
}

void MainWindow::on_spFilterType_valueChanged(int arg1)
{
    switch (arg1)
    {
    case 1:
        dsp_->getFirfilter ()->tFirMainStruct_.firType =
                FIR_COEFF_LOW;
        ui->lFreqC1->show  ();
        ui->spFreqC1->show ();
        ui->lFreqC2->hide  ();
        ui->spFreqC2->hide ();
        ui->lfilterType_FIR->setText ("LOW PASS");
        break;
    case 2:
        dsp_->getFirfilter ()->tFirMainStruct_.firType =
                FIR_COEFF_HIGH;
        ui->lFreqC1->hide  ();
        ui->spFreqC1->hide ();
        ui->lFreqC2->show  ();
        ui->spFreqC2->show ();
        ui->lfilterType_FIR->setText ("HIGH PASS");
        break;
    case 3:
        dsp_->getFirfilter ()->tFirMainStruct_.firType =
                FIR_COEFF_STOP;
        ui->lFreqC1->show  ();
        ui->spFreqC1->show ();
        ui->lFreqC2->show  ();
        ui->spFreqC2->show ();
        ui->lfilterType_FIR->setText ("STOP BAND");
        break;
    case 4:
        dsp_->getFirfilter ()->tFirMainStruct_.firType =
                FIR_COEFF_BAND;
        ui->lFreqC1->show  ();
        ui->spFreqC1->show ();
        ui->lFreqC2->show  ();
        ui->spFreqC2->show ();
        ui->lfilterType_FIR->setText ("PASS BAND");
        break;
    }

    /* On filter type selection the coef are re-calculated. Re-calculation of
     * window is not needed.
     */
    dsp_->getFirfilter ()->FirCoeff (
                dsp_->getFirfilter ()->tFirMainStruct_.coefs,
                dsp_->getFirfilter ()->tFirMainStruct_.fir_order,
                dsp_->getFirfilter ()->tFirMainStruct_.fir_fc,
                dsp_->getFirfilter ()->tFirMainStruct_.firType,
                dsp_->getFirfilter ()->tFirMainStruct_.window);
}

void MainWindow::on_spFilterWindowType_valueChanged(int arg1)
{
    switch (arg1)
    {
    case 1:
        dsp_->getFirfilter ()->tFirMainStruct_.firWinType =
                FIR_COEFF_WIND_RECT;
        ui->lWindowType_FIR->setText ("RECT");
        break;
    case 2:
        dsp_->getFirfilter ()->tFirMainStruct_.firWinType  =
                FIR_COEFF_WIND_HAMM;
        ui->lWindowType_FIR->setText ("HAMMING");
        break;
    case 3:
        dsp_->getFirfilter ()->tFirMainStruct_.firWinType =
                FIR_COEFF_WIND_HANN;
        ui->lWindowType_FIR->setText ("HANNING");
        break;
    case 4:
        dsp_->getFirfilter ()->tFirMainStruct_.firWinType =
                FIR_COEFF_WIND_BLACK;
        ui->lWindowType_FIR->setText ("BLACKMAN");
        break;
    }

    /* A Hard recalculation of parameters is needed when window type is made
     * window and coeff are recalculated
     */
    dsp_->getFirfilter ()->GetWindow (
                dsp_->getFirfilter ()->tFirMainStruct_.window,
                dsp_->getFirfilter ()->tFirMainStruct_.firWinType,
                dsp_->getFirfilter ()->tFirMainStruct_.fir_order+1);

    dsp_->getFirfilter ()->FirCoeff (
                dsp_->getFirfilter ()->tFirMainStruct_.coefs,
                dsp_->getFirfilter ()->tFirMainStruct_.fir_order,
                dsp_->getFirfilter ()->tFirMainStruct_.fir_fc,
                dsp_->getFirfilter ()->tFirMainStruct_.firType,
                dsp_->getFirfilter ()->tFirMainStruct_.window);
}

void MainWindow::on_firinfo_clicked()
{
    /* information of firfilter is stored into file fir_filter_info.txt */
    dsp_->getFirfilter ()->GetFirInfo (&dsp_->getFirfilter ()->tFirMainStruct_);
}

void MainWindow::on_spFIlterOrder_IIR_valueChanged(int arg1)
{
    dsp_->getIirfilter ()->tIirMainStruct_.iir_order = arg1;

    /* re-calculation of arguments (coefs) is need when the filter order
     * is changed
     */
    dsp_->getIirfilter ()->setArguments (
                &dsp_->getIirfilter ()->tIirMainStruct_);
}

void MainWindow::on_spCutFreq1_IIR_valueChanged(int arg1)
{
    float fc_norm = static_cast<float>(arg1);
    dsp_->getIirfilter ()->tIirMainStruct_.iir_fc1 = fc_norm;

    /* re-calculation of arguments (coefs) is need when the filter low pass cut
     * freq is changed
     */
    dsp_->getIirfilter ()->setArguments (
                &dsp_->getIirfilter ()->tIirMainStruct_);
}


void MainWindow::on_cb_lowpass_toggled(bool checked)
{
    if (checked == true)
    {
        ui->cb_highpass->setChecked (false);
        dsp_->getIirfilter ()->tIirMainStruct_.iirType = IIR_COEFF_LOW;

        /* hide low pass spinbox and label */
        ui->spCutFreq1_IIR->show ();
        ui->spCutFreq2_IIR->hide ();
        ui->lCutFreq1_IIR->show ();
        ui->lCutFreq2_IIR->hide ();

        /* re-calculation of arguments (coefs) is need when the filter type is
         * changed
         */
        dsp_->getIirfilter ()->setArguments (
                    &dsp_->getIirfilter ()->tIirMainStruct_);
    }
    else
    {
        ui->cb_highpass->setChecked (true);
    }
}

void MainWindow::on_cb_highpass_toggled(bool checked)
{
    if (checked == true)
    {
        ui->cb_lowpass->setChecked (false);
        dsp_->getIirfilter ()->tIirMainStruct_.iirType = IIR_COEFF_HIGH;

        /* hide low pass spinbox and label */
        ui->spCutFreq1_IIR->hide ();
        ui->spCutFreq2_IIR->show ();
        ui->lCutFreq1_IIR->hide  ();
        ui->lCutFreq2_IIR->show  ();

        /* re-calculation of arguments (coefs) is need when the filter type is
         * changed
         */
        dsp_->getIirfilter ()->setArguments (
                    &dsp_->getIirfilter ()->tIirMainStruct_);
    }
    else
    {
        ui->cb_lowpass->setChecked (true);
    }
}

void MainWindow::on_spCutFreq2_IIR_valueChanged(int arg1)
{
    float fc_norm = static_cast<float>(arg1);
    dsp_->getIirfilter ()->tIirMainStruct_.iir_fc2 = fc_norm;

    /* re-calculation of arguments (coefs) is need when the filter high pass cut
     * freq is changed
     */
    dsp_->getIirfilter ()->setArguments (
                &dsp_->getIirfilter ()->tIirMainStruct_);
}


void MainWindow::on_pushButton_clicked()
{
    /* information of iirfilter is stored into file iir_filter_info.txt */
    dsp_->getIirfilter ()->GetIirInfo (&dsp_->getIirfilter ()->tIirMainStruct_);
}


